package org.changs.launcher.sound;

import android.content.Context;
import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.graphics.PixelFormat;
import android.graphics.drawable.AnimationDrawable;
import android.os.Handler;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;

import com.txznet.sdk.TXZAsrManager;
import com.txznet.sdk.TXZConfigManager;
import com.txznet.sdk.TXZNavManager;
import com.txznet.sdk.TXZResourceManager;
import com.txznet.sdk.TXZSysManager;

import org.changs.aplug.utils.JsonUtils;
import org.changs.launcher.R;
import org.changs.launcher.databinding.LayoutSoundAddressBinding;
import org.changs.launcher.databinding.LayoutSoundControllerBinding;
import org.changs.s3.common.SoundCmdReceiver;
import org.changs.s3.common.tools.AppTools;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.inject.Inject;

import timber.log.Timber;

/**
 * Created by yincs on 2017/10/13.
 */

public class SoundControllerImpl implements SoundController {
    private final Context mContext;
    private LayoutSoundControllerBinding mControllerBinding;
    private LayoutSoundAddressBinding mAddressBinding;
    private AddressChoiceAdapter mAddressChoiceAdapter;
    private WindowManager mWindowManager;
    private Handler mHandler = new Handler();

    private final SoundRecordWin mSoundRecordWin;
    private final S3NavTool mS3NavTool;
    private TXZResourceManager.RecordWin.RecordWinOperateListener mRecordWinOperate;

    @Inject
    public SoundControllerImpl(Context context) {
        this.mContext = context;
        mS3NavTool = new S3NavTool(context);
        mSoundRecordWin = new SoundRecordWin();
    }

    @Override
    public void onCreate() {
        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);

        LayoutInflater inflater = LayoutInflater.from(mContext);
        mControllerBinding = DataBindingUtil.inflate(inflater, R.layout.layout_sound_controller, null, false);
        WindowManager.LayoutParams controllerParams = new WindowManager.LayoutParams();
        controllerParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        controllerParams.height = (int) mContext.getResources().getDimension(R.dimen.PX110);
        controllerParams.gravity = Gravity.BOTTOM;
        controllerParams.type = WindowManager.LayoutParams.TYPE_TOAST;
        controllerParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        controllerParams.format = PixelFormat.RGBA_8888;
        mControllerBinding.getRoot().setLayoutParams(controllerParams);
        mControllerBinding.getRoot().setOnClickListener(v -> {
            if (removeView(mAddressBinding.getRoot())) {
                if (mRecordWinOperate != null) mRecordWinOperate.onClickCancel();
            } else {
                removeView(mControllerBinding.getRoot());
                if (mRecordWinOperate != null) mRecordWinOperate.onClose();
            }
        });

        mAddressBinding = DataBindingUtil.inflate(inflater, R.layout.layout_sound_address, null, false);
        WindowManager.LayoutParams addressParams = new WindowManager.LayoutParams();
        addressParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        addressParams.height = WindowManager.LayoutParams.MATCH_PARENT;
        addressParams.type = WindowManager.LayoutParams.TYPE_TOAST;
        addressParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        addressParams.format = PixelFormat.RGBA_8888;
        mAddressBinding.getRoot().setLayoutParams(addressParams);
        mAddressBinding.getRoot().setOnClickListener(v -> removeView(mAddressBinding.getRoot()));

        initTxz();
    }


    private void initTxz() {
        TXZConfigManager.InitListener initListener = new TXZConfigManager.InitListener() {
            @Override
            public void onSuccess() {
                // TODO 初始化成功，可以在这里根据需要执行一些初始化操作，参考其他Activity
                // TODO 设置一些参数(参考ConfigActivity)
                // TODO 注册指令(参考AsrActivity)
                // TODO 设置电话(参考CallActivity)、音乐(参考MusicActivity)、导航(参考NavActivity)工具
                // TODO 同步联系人(参考CallActivity)
//                TXZTtsManager.getInstance().speakText("大宝引擎初始化成功");
                Timber.d("大宝引擎初始化成功 onSuccess()");
                TXZConfigManager.getInstance().setChatMaxUnknow(3);
                TXZConfigManager.getInstance().setChatMaxEmpty(3);


                TXZResourceManager.getInstance().setRecordWin(mSoundRecordWin);
                TXZNavManager.getInstance().setNavTool(mS3NavTool);
                TXZSysManager.getInstance().setAppMgrTool(new TXZSysManager.AppMgrTool() {
                    @Override
                    public void openApp(String packageName) {
                        AppTools.launcher(mContext, packageName);
                    }

                    @Override
                    public void closeApp(String packageName) {
                        SoundCmdReceiver.sendBroadcast(mContext, null, SoundCmdReceiver.CMD_EXIT, packageName);
                    }
                });
                //注册默认命令处理
                regDefaultCommand();
            }

            @Override
            public void onError(int i, String s) {
                Timber.d("大宝引擎初始化失败 onError() called with: " + "i = [" + i + "], s = [" + s + "]");
            }
        };
        boolean initedSuccess = TXZConfigManager.getInstance().isInitedSuccess();
        Timber.d("TXZConfigManager initedSuccess = " + initedSuccess);
        if (initedSuccess) {
            initListener.onSuccess();
            return;
        }
        Timber.d("initTXZ: 正在初始化同行者 initedSuccess = " + initedSuccess);
        String appId = "ab288f507f22434c2a8c9d84e056b693";
        String appToken = "adb12924bb6b2d5145933955db2ca15c3ed26341";
        TXZConfigManager.InitParam mInitParam = new TXZConfigManager
                .InitParam(appId, appToken)
                .setAppCustomId("ABCDEFGE")
                .setUUID(UUID.randomUUID().toString())
                .setAsrType(TXZConfigManager.AsrEngineType.ASR_YUNZHISHENG)
                .setAsrMode(TXZConfigManager.AsrMode.ASR_MODE_CHAT)
                .setTtsType(TXZConfigManager.TtsEngineType.TTS_YUNZHISHENG)
                .setWakeupKeywordsNew("大宝");


        final TXZConfigManager configManager = TXZConfigManager.getInstance();
        configManager.initialize(mContext, mInitParam, initListener, () -> {
            Timber.d("onFirstActived()");
        });
    }


    @Override
    public void onStartCommand(Intent intent, int flags, int startId) {

    }

    private void regDefaultCommand() {
        for (Map.Entry<String, List<String>> entry : SoundCmdReceiver.getDefaultCommand().entrySet()) {
            TXZAsrManager.getInstance().regCommand(entry.getValue(), entry.getKey());
        }
        TXZAsrManager.getInstance().addCommandListener((cmd, data) -> {
            boolean contains = SoundCmdReceiver.getDefaultCommand().keySet().contains(data);
            if (contains) SoundCmdReceiver.sendBroadcast(mContext, cmd, data);
        });
    }

    @Override
    public void onDestroy() {
        removeView(mControllerBinding.getRoot());
        removeView(mAddressBinding.getRoot());

        TXZAsrManager.getInstance().unregCommand(SoundCmdReceiver.getDefaultCommand().keySet());
    }

    @Override
    public void open() {
        mControllerBinding.tvRequest.setText("...");
        addView(mControllerBinding.getRoot());
    }

    @Override
    public void close() {
        removeView(mControllerBinding.getRoot());
    }


    @Override
    public void startRecording() {
        mControllerBinding.ivControlRecording.setVisibility(View.VISIBLE);
        ((AnimationDrawable) mControllerBinding.ivControlRecording.getDrawable()).start();
    }

    @Override
    public void startRecognizing() {
        mControllerBinding.ivControlRecording.setVisibility(View.VISIBLE);
        ((AnimationDrawable) mControllerBinding.ivControlRecording.getDrawable()).stop();
    }

    @Override
    public void idle() {
        mControllerBinding.ivControlRecording.setVisibility(View.GONE);
        ((AnimationDrawable) mControllerBinding.ivControlRecording.getDrawable()).stop();
    }


    @Override
    public void showUsrText(String msg) {
        mControllerBinding.tvRequest.setText(msg);
    }

    @Override
    public void showSysText(String msg) {
        mControllerBinding.tvResponse.setText(msg);
    }

    @Override
    public void showAddressChoice(PoIResult poIResult) {
        addView(mAddressBinding.getRoot());
        if (mAddressChoiceAdapter == null) {
            mAddressChoiceAdapter = new AddressChoiceAdapter();
            mAddressBinding.rccView.setLayoutManager(new LinearLayoutManager(mContext));
            mAddressBinding.rccView.setAdapter(mAddressChoiceAdapter);
            mAddressBinding.rccView.addItemDecoration(new DividerItemDecoration(mContext, LinearLayoutManager.VERTICAL));
        } else {
            mAddressChoiceAdapter.getData().clear();
        }
        String page = String.format("%d/%d", poIResult.getCurPage(), poIResult.getMaxPage());
        mAddressBinding.tvPage.setText(page);
        mAddressBinding.tvAddress.setText(poIResult.getKeywords());
        mAddressChoiceAdapter.getData().addAll(poIResult.getPois());
        mAddressChoiceAdapter.notifyDataSetChanged();
    }

    @Override
    public void hideAddressChoice() {
        removeView(mAddressBinding.getRoot());
    }

    private boolean addView(View view) {
        try {
            mWindowManager.addView(view, view.getLayoutParams());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private boolean removeView(View view) {
        try {
            mWindowManager.removeView(view);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    private class SoundRecordWin implements TXZResourceManager.RecordWin {

        @Override
        public void showWheatherInfo(String data) {
            log("显示天气数据：" + data);
        }

        @Override
        public void showUsrText(String data) {
            log("显示用户文本：" + data);
            mHandler.post(() -> SoundControllerImpl.this.showUsrText(data));
        }

        @Override
        public void showSysText(String data) {
            log("显示系统文本：" + data);
            mHandler.post(() -> SoundControllerImpl.this.showSysText(data));
        }

        @Override
        public void showStockInfo(String data) {
            log("显示股票数据：" + data);
        }

        @Override
        public void showContactChoice(String data) {
            log("显示联系人选择数据：" + data);
        }

        @Override
        public void showAddressChoice(String data) {
            log("显示地址选择数据：" + data);
            final PoIResult poIResult;
            try {
                poIResult = JsonUtils.parseObject(data, PoIResult.class);
            } catch (Exception e) {
                e.printStackTrace();
                return;
            }
            mHandler.post(() -> SoundControllerImpl.this.showAddressChoice(poIResult));
        }

        @Override
        public void showWxContactChoice(String s) {
        }

        @Override
        public void showAudioChoice(String s) {
        }

        @Override
        public void showListChoice(int i, String s) {
        }

        @Override
        public void snapPager(boolean b) {
        }

        @Override
        public void setOperateListener(RecordWinOperateListener listener) {
            log("通知窗口操作给大宝：" + listener);
            mRecordWinOperate = listener;
        }

        @Override
        public void open() {
            log("打开录音窗口");
            mHandler.post(SoundControllerImpl.this::open);
        }

        @Override
        public void onVolumeChange(int volume) {
            // TODO 处理音量变化
        }

        @Override
        public void onStatusChange(RecordStatus status) {
            log("录音状态变化 status = " + status);
            mHandler.post(() -> {
                if (status == RecordStatus.STATUS_RECORDING) {
                    SoundControllerImpl.this.startRecording();
                } else if (status == RecordStatus.STATUS_RECOGONIZING) {
                    SoundControllerImpl.this.startRecognizing();
                } else {
                    SoundControllerImpl.this.idle();
                }
            });
        }

        @Override
        public void onProgressChanged(int progress) {
            log("onProgressChanged progress = " + progress);
            if (progress == -1) {
                mHandler.post(SoundControllerImpl.this::hideAddressChoice);
            }
        }

        @Override
        public void close() {
            log("关闭录音窗口");
            mHandler.post(SoundControllerImpl.this::close);

        }

        private void log(String msg) {
            Timber.d(msg);
        }

    }
}
